﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using InTheHand.Net.Sockets;
using WinHBM.Utils;
using System.Threading;
using System.IO;
using HbmTools.Utils;
//using WinHBM.Core.Net.Sockets;

namespace WinHBM.Core.Bluetooth
{

    public delegate void OnFlowerData(RedFlower flower);
    public delegate void OnLostConnection();
    public delegate void OnReConnected();
    public delegate void SendCMDByte(byte[] bytes);
    public delegate void ReadCMDByte(byte[] bytes);

    public class MagicBar
    {
        public static readonly byte[] RESP_SUCCESS = { 0x00,0x00,0xFF,0x00,0xFF,0x00 };

        public static readonly byte[] CMD_PREFIX = { 0x00, 0x00, 0xFF };
        //写教师ID
        public static readonly byte[] CMD_WRITE_TEACHER_ID = { 0x07,0x02 };
        //读教师ID
        public static readonly byte[] CMD_READ_TEACHER_ID = { 0x03, 0x01 };
        //校准时间
        public static readonly byte[] CMD_GET_NOW_TIME = { 0x0A,0x08};
        //读红花卡
        public static readonly byte[] CMD_READ_CARD = {0x03,0x03};
        //写红花卡 
        public static readonly byte[] CMD_WRITE_CARD = { 0x07, 0x04 };
        //检查音频文件
        public static readonly byte[] CMD_SETTING_VOICE = { 0x04, 0x09 };
        //设置音量
        public static readonly byte[] CMD_CHECK_AUDIO  = { 0x07, 0x07 };
        //返回电池电量
        public static readonly byte[] CMD_GET_BATTERY = { 0x03, 0x0E };
        //返回缓存红花信息
        public static readonly byte[] CMD_GET_CACHE_FLOWER = { 0x03,0x06 };
        //返回缓存签到数据
        public static readonly byte[] CMD_GET_CACHE_SIGN = { 0x03 ,0x05 };
        //返回缓存红花总数
        public static readonly byte[] CMD_GET_CACHE_FLOWER_COUNT = { 0x03, 0x0C };
        //返回缓存签到.签退总数
        public static readonly byte[] CMD_GET_CACHE_SIGN_COUNT = { 0x03, 0x0D };
        //擦除Flash
        public static readonly byte[] CMD_CLEAR_FLASH = { 0x03, 0x19 };

        public event OnFlowerData OnFlowerData;
        public event OnLostConnection OnLostConnection;
        public event OnReConnected OnReConnected;
        public event SendCMDByte SendCMDByte;
        public event ReadCMDByte ReadCMDByte;

        private Thread onlineThread;

      //  private FlashSocketServer flashSocketServer = FlashSocketServer.Instance;

        private SynchronizationContext m_SyncContext = null;

        public BluetoothClient bluetoothClient { get; set; }
   

        public MagicBar(BluetoothClient bluetoothClient)
        {
            this.bluetoothClient = bluetoothClient;
        }

        public void Online()
        {
            //m_SyncContext = SynchronizationContext.Current;
            onlineThread = new Thread(OnLineThread);
            onlineThread.IsBackground = false;
            onlineThread.Start();
        }

        public void Offline()
        {
            if(onlineThread != null && onlineThread.IsAlive)
            {
                this.OnLostConnection = null;
                onlineThread.Abort();
            }
            this.OnFlowerData = null;
        }

        private void OnLineThread()
        {
            while(true)
            {
                try
                {
                    Stream stream = bluetoothClient.GetStream();
                    byte[] buffer = new byte[23];
                    Socket s = bluetoothClient.Client;
                    
                    int len = stream.Read(buffer, 0, 23);
                    if(len == 0)
                    {
                        if(this.OnLostConnection != null)
                        {
                            OnLostConnection();
                        }
                        break;
                    }
                    if (len == 23) // 23长度是红花指令数据的长度
                    {
                        SendData(RESP_SUCCESS);
                        if (this.OnFlowerData != null)
                        {
                            RedFlower flower = RedFlower.FromBytes(buffer);
                            this.OnFlowerData(flower);
                        }
                    }
                    
                    

                }catch(Exception e)
                {
                    if (this.OnLostConnection != null)
                    {
                        OnLostConnection();
                    }
                    break;
                }
                
                //如果是网络通信发给Flash，无需切换线程
                //m_SyncContext.Post()
            }
        }
        
        public int CMD_CheckAudioFile(int studentID )
        {
            //声明指令字节数组,长度是8，根据文档设定
            byte[] cmd = new byte[11];

            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_CHECK_AUDIO, 0, cmd, 3, CMD_SETTING_VOICE.Length);
            byte[] studentIDBYTE = Utils.UtilByte.GetBytes(studentID);
            Buffer.BlockCopy(studentIDBYTE, 0, cmd, 5, studentIDBYTE.Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return 0;
            }

            //获取响应结果
            byte[] response = ReadData(7);
            //获取结果中数据部分字节
            byte[] data = PartoOfData(response);
            //将字节转换成int
            int studentId = UtilByte.ToInt32(data);
            return studentId;

        }

        public int CMD_GetCacheSignCount()
        {
            byte[] cmd = new byte[7];
            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_GET_CACHE_SIGN_COUNT, 0, cmd, 3, CMD_GET_CACHE_SIGN_COUNT.Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            Console.WriteLine("返回缓存总数 ：" + BitConverter.ToString(success));
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return -1;
            }
            //获取响应结果
            byte[] response = ReadData(9);
            //将字节转换成int
            int count = response[5] * 256 + response[6];
            return count;
        }




        /// <summary>
        /// 计算校验码
        /// </summary>
        /// <param name="cmd">指令的完整结构字节数组</param>
        /// <returns>计算好的校验码字节</returns>
        protected byte ComputeValidCode(byte[] cmd)
        {
            int sum = 0;
            for (int i = 3; i < cmd.Length - 2; i++)
            {
                sum += cmd[i];
            }
            return (byte)sum;
        }
        
        /// <summary>
        /// 发送指令
        /// </summary>
        /// <param name="data">指令数据</param>
        protected void SendData(byte[] data)
        {
            this.SendCMDByte(data);
            NetworkStream stream = bluetoothClient.GetStream();
            stream.Write(data, 0, data.Length);
            stream.Flush();
        }

        /// <summary>
        /// 读取响应内容
        /// </summary>
        /// <param name="len">预计读取的字节数据长度</param>
        /// <returns>返回读取到的字节数组</returns>
        public byte[] ReadData(int len)
        {
            byte[] buffer = new byte[len];
            NetworkStream stream = bluetoothClient.GetStream();
            stream.Read(buffer, 0, len);
            this.ReadCMDByte(buffer);
            return buffer;
        }

        /// <summary>
        /// 对于响应内容里，需要有数据内容的情况
        /// 该方法会把响应数据中的核心数据部分取出来
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        protected byte[] PartoOfData(byte[] response)
        {
            byte[] data = new byte[response.Length - 6];
            int index = 0;
            for (int i = 4; i < response.Length - 2; i++,index++)
            {
                data[index] = response[i];
            }
            return data;
        }


        /// <summary>
        /// 获取教师ID
        /// </summary>
        /// <returns></returns>
        public int CMD_ReadTeacherId()
        {
            //声明指令字节数组,长度是7，根据文档设定
            byte[] cmd = new byte[7];

            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_READ_TEACHER_ID, 0, cmd,3,CMD_READ_TEACHER_ID.Length);

            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);

            //发送指令
            SendData(cmd);


            //获取响应成功
            byte[] success = ReadData(6);
            if(!UtilByte.BytesCompare_Base64(RESP_SUCCESS,success))
            {
                return -1;
            }

            //获取响应结果
            byte[] response = ReadData(10);
            //获取结果中数据部分字节
            byte[] data = PartoOfData(response);
            //将字节转换成int
            int teacherId = UtilByte.ToInt32(data);
            return teacherId;
        }
        /// <summary>
        /// 绑定教师ID
        /// </summary>
        /// <returns></returns>
        public bool CMD_BindTeacherId(int teacherId)
        {
             
            byte[] cmd = new byte[11];

            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length); 
            Buffer.BlockCopy(CMD_WRITE_TEACHER_ID, 0, cmd, 3, CMD_WRITE_TEACHER_ID.Length); 
            byte[] teacherIdBYTE = Utils.UtilByte.GetBytes(teacherId);
            Buffer.BlockCopy(teacherIdBYTE, 0, cmd, 5, teacherIdBYTE.Length); 
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //
            //发送指令
            SendData(cmd); 
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return false;
            }
            else
            {
                return true;
            }
             
        }
        /// <summary>
        /// 校准时间
        /// </summary>
        /// <returns></returns>
        public bool CMD_GetNowTime()
        {
            //声明指令字节数组,长度是7，根据文档设定
            byte[] cmd = new byte[14];

            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_GET_NOW_TIME, 0, cmd, 3, CMD_GET_NOW_TIME.Length);   
            Buffer.BlockCopy(UtilByte.GetTimeBytes(), 0, cmd,5, UtilByte.GetTimeBytes().Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return false;
            }
            else
            {
                return true;
            }

        }

        /// <summary>
        /// 读红花卡
        /// </summary>
        /// <returns></returns>
        public int CMD_ReadRedCard()
        {
            //声明指令字节数组,长度是7，根据文档设定
            byte[] cmd = new byte[7];

            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_READ_CARD, 0, cmd, 3, CMD_READ_CARD.Length); 
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return -1;
            }

            //获取响应结果
            byte[] response = ReadData(10);
            //获取结果中数据部分字节
            byte[] data = PartoOfData(response);
            //将字节转换成int
            int studentId = UtilByte.ToInt32(data);
            return studentId;

        }
        /// <summary>
        /// 写红花卡
        /// </summary>
        /// <returns></returns>
        public bool CMD_WriteRedCard(int number)
        {
            //声明指令字节数组,长度是7，根据文档设定
            byte[] cmd = new byte[11];

            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_WRITE_CARD, 0, cmd, 3, CMD_READ_CARD.Length);
            int length = UtilByte.GetBytes(number).Length;
            Buffer.BlockCopy(UtilByte.GetBytes(number), 0, cmd, 5, UtilByte.GetBytes(number).Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return false;
            }
            else
            {
                return true;
            }

        }
        /// <summary>
        /// 设置音量
        /// </summary>
        /// <returns></returns>
        public bool CMD_SettingVoice(int number)
        {
            //声明指令字节数组,长度是8，根据文档设定
            byte[] cmd = new byte[8];

            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_SETTING_VOICE, 0, cmd, 3, CMD_SETTING_VOICE.Length);
            if (number > 31) {
                number = 31;
            }
            if (number<1)
            {
                number = 1;
            }
            byte[] temp = { UtilByte.GetBytes(number)[3]};
            Buffer.BlockCopy(temp, 0, cmd, 5, temp.Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return false;
            }
            else
            {
                return true;
            }

        }

        public bool CMD_ClearFlash()
        {

            byte[] cmd = new byte[7];
            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_CLEAR_FLASH, 0, cmd, 3, CMD_CLEAR_FLASH.Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return false;
            }

            return true;

        }

        /// <summary>
        /// 返回电量
        /// </summary>
        /// <returns></returns>
        public int CMD_GetBattery()
        {
             
            byte[] cmd = new byte[7]; 
            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_GET_BATTERY, 0, cmd, 3, CMD_GET_BATTERY.Length); 
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return -1;
            }
            //获取响应结果
            byte[] response = ReadData(8);  
            //将字节转换成int
            int battery = response[4]*256 + response[5];
            return battery;

        }
        /// <summary>
        /// 返回红花缓存总数
        /// </summary>
        /// <returns></returns>
        public int CMD_GetCacheFlowerCount()
        {

            byte[] cmd = new byte[7];
            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_GET_CACHE_FLOWER_COUNT, 0, cmd, 3, CMD_GET_CACHE_FLOWER_COUNT.Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            Console.WriteLine("返回缓存总数 ：" + BitConverter.ToString(success));
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return -1;
            }
            //获取响应结果
            byte[] response = ReadData(9);
            //将字节转换成int
            int count = response[5] * 256 + response[6];
            return count;

        }
        /// <summary>
        /// 返回缓存红花数据
        /// </summary>
        /// <returns></returns>
        public RedFlower CMD_GetRedData()
        {
            byte[] cmd = new byte[7];
            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_GET_CACHE_FLOWER, 0, cmd, 3, CMD_GET_CACHE_FLOWER.Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6); 
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return null;
            }
            //获取响应结果
            byte[] response = ReadData(23);
            SendData(RESP_SUCCESS);
            byte[] success1 = ReadData(6);
            RedFlower flower = RedFlower.FromBytes(response);
            return flower;

        }


        // 获取缓存签到数据
        
        public RedFlower CMD_ReadCacheSign()
        {
            byte[] cmd = new byte[7];
            //拷贝指令的开始部分和指令码和长度位
            Buffer.BlockCopy(CMD_PREFIX, 0, cmd, 0, CMD_PREFIX.Length);
            Buffer.BlockCopy(CMD_GET_CACHE_SIGN, 0, cmd, 3, CMD_GET_CACHE_SIGN.Length);
            //计算指令的校验码
            cmd[cmd.Length - 2] = this.ComputeValidCode(cmd);
            //发送指令
            SendData(cmd);
            //获取响应成功
            byte[] success = ReadData(6);
            if (!UtilByte.BytesCompare_Base64(RESP_SUCCESS, success))
            {
                return null;
            }
            //获取响应结果
            byte[] response = ReadData(23);
            SendData(RESP_SUCCESS);
            byte[] success1 = ReadData(6);
            RedFlower flower = RedFlower.FromBytes(response);
            return flower;
        }



        public void ClearReadBuffer()
        {
            
            NetworkStream stream = bluetoothClient.GetStream();
            int before = stream.ReadTimeout;
            stream.ReadTimeout = 2;
            try
            {
                while (true)
                {
                    byte[] buffer = new byte[100];
                    stream.Read(buffer, 0, buffer.Length);
                }
            }
            catch (Exception e)
            {
                stream.ReadTimeout = before;
            }
            
            
        }
        //发送红花数据 年      月 日   时 分   秒 学生ID 教师ID  大红花（A）\小红花（B）  校验码
        //0x00 0x00 0xFF 
        //0x13 0xA2 
        //0x00 0x00 0x00 0x00 0x00 0x00 0x00
        //0x00 0x00 0x00 0x01
        //0x00 0x00 0x00 0x01          
        //0x41（A）/0x42（B）          
        //0xF8  0x00       
    }
}
